package com.pokermind.model.po;

import java.math.BigDecimal;

/**
 * 扑克手牌实体类 支持完整的手牌生命周期管理
 * 对应 poker_hands 表
 *
 * @author PokerMind Team
 */
public class PokerHand {

    /** 主键ID */
    private Long id;

    /** 外部系统手牌标识 */
    private String handId;

    /** 桌子标识 */
    private String tableId;

    /** 用户ID */
    private Long userId;

    /** 庄家按钮位置 */
    private Integer buttonSeat;

    /** 小盲金额 */
    private BigDecimal smallBlind;

    /** 大盲金额 */
    private BigDecimal bigBlind;

    /** 前注金额 */
    private BigDecimal ante;

    /** 发牌玩家数 */
    private Integer playersDealt;

    /** Hero座位号 */
    private Integer heroSeatNumber;

    /** Hero位置 */
    private String heroPosition;

    /** Hero底牌 JSON格式 */
    private String heroHoleCards;

    /** Hero起始筹码 */
    private BigDecimal heroStackStart;

    /** 当前街道 */
    private String currentStreet;

    /** 公共牌 JSON格式 */
    private String boardCards;

    /** 当前底池 */
    private BigDecimal currentPot;

    /** 下一个行动座位 */
    private Integer nextActionSeat;

    /** 活跃玩家数 */
    private Integer activePlayers;

    /** 当前需要跟注金额 */
    private BigDecimal toCall;

    /** 最小加注金额 */
    private BigDecimal minRaise;

    /** 手牌状态 */
    private String status;

    /** Hero净盈亏 */
    private BigDecimal heroNetResult;

    /** Hero最后行动 */
    private String heroFinalAction;

    /** Hero是否到摊牌 */
    private Boolean heroWentToShowdown;

    /** 最终底池 */
    private BigDecimal finalPot;

    /** 抽水金额 */
    private BigDecimal rakeAmount;

    /** 看到翻牌的玩家数 */
    private Integer playersToFlop;

    /** 看到转牌的玩家数 */
    private Integer playersToTurn;

    /** 看到河牌的玩家数 */
    private Integer playersToRiver;

    /** 摊牌玩家数 */
    private Integer playersToShowdown;

    /** 总行动数 */
    private Integer totalActions;

    /** 手牌创建时间戳(毫秒) */
    private Long createTime;
    
    /** 手牌更新时间戳(毫秒) */
    private Long updateTime;

    /** 手牌完成时间戳(毫秒) */
    private Long completedTime;

    /** 持续时间（秒） */
    private Integer durationSeconds;

    /** 玩家信息 JSON格式 */
    private String playersInfo;

    /** 最终结果 JSON格式 */
    private String finalResults;

    /** 是否启用Run It Twice */
    private Boolean runItTwice;

    /** Run It Twice详细结果 JSON格式 */
    private String runTwiceDetails;

    // 手牌状态常量
    public static final String STATUS_ACTIVE = "active";
    public static final String STATUS_COMPLETED = "completed";
    public static final String STATUS_CANCELLED = "cancelled";

    // 街道常量
    public static final String STREET_PREFLOP = "preflop";
    public static final String STREET_FLOP = "flop";
    public static final String STREET_TURN = "turn";
    public static final String STREET_RIVER = "river";

    // 位置常量
    public static final String POSITION_BTN = "BTN";
    public static final String POSITION_SB = "SB";
    public static final String POSITION_BB = "BB";
    public static final String POSITION_UTG = "UTG";
    public static final String POSITION_MP = "MP";
    public static final String POSITION_CO = "CO";

    // 默认构造函数
    public PokerHand() {
        this.currentStreet = STREET_PREFLOP;
        this.status = STATUS_ACTIVE;
        this.currentPot = BigDecimal.ZERO;
        this.heroWentToShowdown = false;
        this.totalActions = 0;
        this.createTime = System.currentTimeMillis();
        this.updateTime = System.currentTimeMillis();
    }

    // V4.8: 业务构造函数 - 移除 smallBlind 和 bigBlind 参数
    // 盲注字段保留在数据库中（用于记录历史配置），但创建时不再需要
    public PokerHand(String handId, String tableId, Long userId, Integer buttonSeat, Integer playersDealt) {
        this();
        this.handId = handId;
        this.tableId = tableId;
        this.userId = userId;
        this.buttonSeat = buttonSeat;
        this.playersDealt = playersDealt;
        // smallBlind 和 bigBlind 通过 setter 设置（如需记录）
    }

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getHandId() {
        return handId;
    }

    public void setHandId(String handId) {
        this.handId = handId;
    }

    public String getTableId() {
        return tableId;
    }

    public void setTableId(String tableId) {
        this.tableId = tableId;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public Integer getButtonSeat() {
        return buttonSeat;
    }

    public void setButtonSeat(Integer buttonSeat) {
        this.buttonSeat = buttonSeat;
    }

    public BigDecimal getSmallBlind() {
        return smallBlind;
    }

    public void setSmallBlind(BigDecimal smallBlind) {
        this.smallBlind = smallBlind;
    }

    public BigDecimal getBigBlind() {
        return bigBlind;
    }

    public void setBigBlind(BigDecimal bigBlind) {
        this.bigBlind = bigBlind;
    }

    public BigDecimal getAnte() {
        return ante;
    }

    public void setAnte(BigDecimal ante) {
        this.ante = ante;
    }

    public Integer getPlayersDealt() {
        return playersDealt;
    }

    public void setPlayersDealt(Integer playersDealt) {
        this.playersDealt = playersDealt;
    }

    public Integer getHeroSeatNumber() {
        return heroSeatNumber;
    }

    public void setHeroSeatNumber(Integer heroSeatNumber) {
        this.heroSeatNumber = heroSeatNumber;
    }

    public String getHeroPosition() {
        return heroPosition;
    }

    public void setHeroPosition(String heroPosition) {
        this.heroPosition = heroPosition;
    }

    public String getHeroHoleCards() {
        return heroHoleCards;
    }

    public void setHeroHoleCards(String heroHoleCards) {
        this.heroHoleCards = heroHoleCards;
    }

    public BigDecimal getHeroStackStart() {
        return heroStackStart;
    }

    public void setHeroStackStart(BigDecimal heroStackStart) {
        this.heroStackStart = heroStackStart;
    }

    public String getCurrentStreet() {
        return currentStreet;
    }

    public void setCurrentStreet(String currentStreet) {
        this.currentStreet = currentStreet;
    }

    public String getBoardCards() {
        return boardCards;
    }

    public void setBoardCards(String boardCards) {
        this.boardCards = boardCards;
    }

    public BigDecimal getCurrentPot() {
        return currentPot;
    }

    public void setCurrentPot(BigDecimal currentPot) {
        this.currentPot = currentPot;
    }

    public Integer getNextActionSeat() {
        return nextActionSeat;
    }

    public void setNextActionSeat(Integer nextActionSeat) {
        this.nextActionSeat = nextActionSeat;
    }

    public Integer getActivePlayers() {
        return activePlayers;
    }

    public void setActivePlayers(Integer activePlayers) {
        this.activePlayers = activePlayers;
    }

    public BigDecimal getToCall() {
        return toCall;
    }

    public void setToCall(BigDecimal toCall) {
        this.toCall = toCall;
    }

    public BigDecimal getMinRaise() {
        return minRaise;
    }

    public void setMinRaise(BigDecimal minRaise) {
        this.minRaise = minRaise;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public BigDecimal getHeroNetResult() {
        return heroNetResult;
    }

    public void setHeroNetResult(BigDecimal heroNetResult) {
        this.heroNetResult = heroNetResult;
    }

    public String getHeroFinalAction() {
        return heroFinalAction;
    }

    public void setHeroFinalAction(String heroFinalAction) {
        this.heroFinalAction = heroFinalAction;
    }

    public Boolean getHeroWentToShowdown() {
        return heroWentToShowdown;
    }

    public void setHeroWentToShowdown(Boolean heroWentToShowdown) {
        this.heroWentToShowdown = heroWentToShowdown;
    }

    public BigDecimal getFinalPot() {
        return finalPot;
    }

    public void setFinalPot(BigDecimal finalPot) {
        this.finalPot = finalPot;
    }

    public BigDecimal getRakeAmount() {
        return rakeAmount;
    }

    public void setRakeAmount(BigDecimal rakeAmount) {
        this.rakeAmount = rakeAmount;
    }

    public Integer getPlayersToFlop() {
        return playersToFlop;
    }

    public void setPlayersToFlop(Integer playersToFlop) {
        this.playersToFlop = playersToFlop;
    }

    public Integer getPlayersToTurn() {
        return playersToTurn;
    }

    public void setPlayersToTurn(Integer playersToTurn) {
        this.playersToTurn = playersToTurn;
    }

    public Integer getPlayersToRiver() {
        return playersToRiver;
    }

    public void setPlayersToRiver(Integer playersToRiver) {
        this.playersToRiver = playersToRiver;
    }

    public Integer getPlayersToShowdown() {
        return playersToShowdown;
    }

    public void setPlayersToShowdown(Integer playersToShowdown) {
        this.playersToShowdown = playersToShowdown;
    }

    public Integer getTotalActions() {
        return totalActions;
    }

    public void setTotalActions(Integer totalActions) {
        this.totalActions = totalActions;
    }

    public Long getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Long createTime) {
        this.createTime = createTime;
    }
    
    public Long getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Long updateTime) {
        this.updateTime = updateTime;
    }

    public Long getCompletedTime() {
        return completedTime;
    }

    public void setCompletedTime(Long completedTime) {
        this.completedTime = completedTime;
    }

    public Integer getDurationSeconds() {
        return durationSeconds;
    }

    public void setDurationSeconds(Integer durationSeconds) {
        this.durationSeconds = durationSeconds;
    }

    public String getPlayersInfo() {
        return playersInfo;
    }

    public void setPlayersInfo(String playersInfo) {
        this.playersInfo = playersInfo;
    }

    public String getFinalResults() {
        return finalResults;
    }

    public void setFinalResults(String finalResults) {
        this.finalResults = finalResults;
    }

    public Boolean getRunItTwice() {
        return runItTwice;
    }

    public void setRunItTwice(Boolean runItTwice) {
        this.runItTwice = runItTwice;
    }

    public String getRunTwiceDetails() {
        return runTwiceDetails;
    }

    public void setRunTwiceDetails(String runTwiceDetails) {
        this.runTwiceDetails = runTwiceDetails;
    }

    // 业务方法

    /**
     * 完成手牌
     */
    public void complete(BigDecimal netResult, String finalAction, BigDecimal finalPot, Integer playersToShowdown,
        String finalResults) {
        this.heroNetResult = netResult;
        this.heroFinalAction = finalAction;
        this.finalPot = finalPot;
        this.playersToShowdown = playersToShowdown;
        this.finalResults = finalResults;
        this.status = STATUS_COMPLETED;
        this.completedTime = System.currentTimeMillis();
        this.updateTime = System.currentTimeMillis();

        if (this.createTime != null && this.completedTime != null) {
            this.durationSeconds = (int)((this.completedTime - this.createTime) / 1000);
        }
    }

    /**
     * 检查是否已完成
     */
    public boolean isCompleted() {
        return STATUS_COMPLETED.equals(status);
    }

    /**
     * 检查是否激活状态
     */
    public boolean isActive() {
        return STATUS_ACTIVE.equals(status);
    }

    /**
     * 转换到下一个街道
     */
    public void advanceToStreet(String newStreet, String boardCards, Integer activePlayers) {
        this.currentStreet = newStreet;
        this.boardCards = boardCards;
        this.activePlayers = activePlayers;

        // 根据街道更新统计
        switch (newStreet) {
            case STREET_FLOP:
                this.playersToFlop = activePlayers;
                break;
            case STREET_TURN:
                this.playersToTurn = activePlayers;
                break;
            case STREET_RIVER:
                this.playersToRiver = activePlayers;
                break;
        }
    }

    /**
     * 增加行动计数
     */
    public void incrementActionCount() {
        this.totalActions = (this.totalActions == null ? 0 : this.totalActions) + 1;
    }

    /**
     * 计算Hero位置
     */
    public static String calculatePosition(Integer heroSeat, Integer buttonSeat, Integer playersDealt) {
        if (heroSeat == null || buttonSeat == null || playersDealt == null) {
            return null;
        }

        int relativeSeat = (heroSeat - buttonSeat + playersDealt) % playersDealt;

        if (playersDealt == 6) {
            switch (relativeSeat) {
                case 0:
                    return POSITION_BTN;
                case 1:
                    return POSITION_SB;
                case 2:
                    return POSITION_BB;
                case 3:
                    return POSITION_UTG;
                case 4:
                    return POSITION_MP;
                case 5:
                    return POSITION_CO;
                default:
                    return "UNKNOWN";
            }
        }

        // 可以扩展支持其他玩家数量
        return "UNKNOWN";
    }

    @Override
    public String toString() {
        return "PokerHand{" + "id=" + id + ", handId='" + handId + '\'' + ", tableId='" + tableId + '\'' + ", heroPosition='" + heroPosition + '\'' + ", currentStreet='" + currentStreet + '\'' + ", status='" + status + '\'' + ", currentPot=" + currentPot + '}';
    }
}